import CryptoJS from 'crypto-js';

// 定义加密密钥（实际项目中应从安全配置中获取）
const ENCRYPTION_KEY = import.meta.env.VITE_CRYPTO_KEY || 'zWGt1Pft4kx1X2gL';
const ENCRYPTION_IV = import.meta.env.VITE_CRYPTO_IV || 'vw3Io3HRa7vlgsBG';

// 类型定义
type EncryptionOptions = {
    iv?: string;
};

/**
 * 加密数据
 * @param data 需要加密的数据（对象或字符串）
 * @param key 加密密钥（可选）
 * @param options
 * @returns 加密后的 Base64 字符串
 */
export const encrypt = <T extends object | string>(
    data: T,
    key: string = ENCRYPTION_KEY,
    options: EncryptionOptions = {
        iv: ENCRYPTION_IV,
    },
): string => {
    try {
        const plaintext =
            typeof data === 'string' ? data : JSON.stringify(data);
        const keyStr = key ? encParse(key) : encParse(ENCRYPTION_KEY);
        const ivStr = options.iv
            ? encParse(options.iv)
            : encParse(ENCRYPTION_IV);

        const ciphertext = CryptoJS.AES.encrypt(plaintext, keyStr, {
            iv: ivStr,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
        });

        // 返回 IV + 加密内容 的Base64字符串
        return ciphertext.toString();
    } catch (error) {
        console.error('Encryption error:', error);
        throw new Error('Failed to encrypt data');
    }
};

/**
 * 解密数据
 * @param encryptedData 加密的Base64字符串
 * @param key 加密密钥（可选）
 * @param iv
 * @returns 解密后的原始数据
 */
export const decrypt = <T = any>(
    encryptedData: string,
    key: string = ENCRYPTION_KEY,
    iv: string = ENCRYPTION_IV,
): T => {
    try {
        encryptedData = (encryptedData + '')
            .replace(/\n*$/g, '')
            .replace(/\n/g, '');
        const keyStr = key ? encParse(key) : encParse(ENCRYPTION_KEY);
        const ivStr = iv ? encParse(iv) : encParse(ENCRYPTION_IV);
        const decryptedBytes = CryptoJS.AES.decrypt(encryptedData, keyStr, {
            iv: ivStr,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
        });

        const decryptedText = decryptedBytes.toString(CryptoJS.enc.Utf8);

        try {
            // 尝试解析为JSON对象
            return JSON.parse(decryptedText);
        } catch {
            // 解析失败则返回字符串
            return decryptedText as any;
        }
    } catch (error) {
        console.error('Decryption error:', error);
        throw new Error('Failed to decrypt data');
    }
};
export const encParse = (key: string) => {
    // return CryptoJs.enc.Utf8.parse(key);
    return CryptoJS.enc.Latin1.parse(key);
};
/**
 * 生成随机的AES密钥（256位）
 * @returns Base64格式的密钥
 */
export const generateKey = (): string => {
    return CryptoJS.lib.WordArray.random(32).toString();
};

/**
 * 生成随机的初始化向量（IV）
 * @returns Base64格式的IV
 */
export const generateIv = (): string => {
    return CryptoJS.lib.WordArray.random(16).toString();
};

/**
 * 创建HMAC签名
 * @param data 要签名的数据
 * @param key 签名密钥（可选）
 * @returns Base64格式的签名
 */
export const sign = (
    data: object | string,
    key: string = ENCRYPTION_KEY,
): string => {
    const payload = typeof data === 'string' ? data : JSON.stringify(data);
    return CryptoJS.HmacSHA256(payload, key).toString();
};

/**
 * 验证HMAC签名
 * @param data 原始数据
 * @param signature 要验证的签名
 * @param key 签名密钥（可选）
 * @returns 签名是否有效
 */
export const verify = (
    data: object | string,
    signature: string,
    key: string = ENCRYPTION_KEY,
): boolean => {
    const newSignature = sign(data, key);
    return newSignature === signature;
};

/**
 * 简化的加密函数（使用默认设置）
 */
export const simpleEncrypt = (text: string): string => {
    return CryptoJS.AES.encrypt(text, ENCRYPTION_KEY).toString();
};

/**
 * 简化的解密函数
 */
export const simpleDecrypt = (ciphertext: string): string => {
    const bytes = CryptoJS.AES.decrypt(ciphertext, ENCRYPTION_KEY);
    return bytes.toString(CryptoJS.enc.Utf8);
};

/**
 * 生成密码的哈希值（加盐）
 * @param password 密码
 * @param salt 盐值（可选）
 * @returns 包含盐和哈希值的对象
 */
export const hashPassword = (
    password: string,
    salt?: string,
): { salt: string; hash: string } => {
    const usedSalt = salt || CryptoJS.lib.WordArray.random(128 / 8).toString();
    const hash = CryptoJS.PBKDF2(password, usedSalt, {
        keySize: 512 / 32,
        iterations: 1000,
    }).toString();

    return { salt: usedSalt, hash };
};

/**
 * 验证密码
 * @param password 密码
 * @param hash 原始哈希值
 * @param salt 盐值
 * @returns 密码是否匹配
 */
export const verifyPassword = (
    password: string,
    hash: string,
    salt: string,
): boolean => {
    const newHash = CryptoJS.PBKDF2(password, salt, {
        keySize: 512 / 32,
        iterations: 1000,
    }).toString();

    return newHash === hash;
};

// 常用哈希函数
export const sha256 = (data: string): string =>
    CryptoJS.SHA256(data).toString();
export const sha512 = (data: string): string =>
    CryptoJS.SHA512(data).toString();
export const md5 = (data: string): string => CryptoJS.MD5(data).toString();

export default {
    encrypt,
    decrypt,
    md5,
};
